package 基础语法.网络编程;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.MulticastSocket;

public class UDP_learn_组播 {

    /**
     * 组播地址是否属于局域网IP？
答案是：部分属于，但不完全是。

✅ 很多组播地址专用于局域网内部：
例如，224.0.0.1（所有主机）、224.0.0.2（所有路由器）等属于“保留组播地址”，仅在本地网络段内有效，不会被路由器转发。这类地址确实只在局域网中使用，类似于广播地址。
     * 
    */
    public static void main(String[] args) throws Exception {//可能需要关闭防火墙

        Thread senThread = new Thread() {
            @Override
            public void run() {
                try {
                    sendData();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };

        Thread receiveThread1 = new Thread() {
            @Override
            public void run() {
                try {
                    super.setName("接收端1");
                    receiveData();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };

        Thread receiveThread2 = new Thread() {
            @Override
            public void run() {
                try {
                    super.setName("接收端2");
                    receiveData();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };
        receiveThread2.start();
        receiveThread1.start();

        senThread.start();

    }

    static void sendData() throws Exception {
        // 发送数据
        // 1.
        // 会绑定端口，若空参，会在所有可用的端口中随机选一个发送，否则，就在指定的端口发送
        MulticastSocket ms = new MulticastSocket();

        // 2.
        String sendData = "你好";// 要发送的内容
        byte[] byteData = sendData.getBytes();// 要发送的内容，子节形式
        Integer sendLength = byteData.length;// 本次发送数组多长的内容
        InetAddress targetAddress = InetAddress.getByName("224.0.0.1");// 一定要指定组播地址
        Integer port = 8080;// 目标主机端口
        DatagramPacket dp = new DatagramPacket(byteData, sendLength, targetAddress, port);// 第二个参数值
        // 3.
        ms.send(dp);// 发送数据
        ms.close();
    }

    static void receiveData() throws Exception {

        // 1.
        // 接受的时候一定要指定监听的端口
        Integer port = 8080;// 与发送的者指定 的端口 一致
        MulticastSocket ms = new MulticastSocket(port);

        // 2.将当前主机添加到224.0.0.1这一组中
        InetAddress iAddress = InetAddress.getByName("224.0.0.1");
        ms.joinGroup(iAddress);

        // 2.接受数据包
        byte[] receiveData = new byte[1024];
        DatagramPacket dp = new DatagramPacket(receiveData, receiveData.length);
        System.out.println(Thread.currentThread().getName() + "等待消息");
        ms.receive(dp);// 阻塞值至接收到消息

        // 3.解析数据包

        byte[] data = dp.getData();// 就是receiveData
        int length = dp.getLength();// 获取了多少字节的数据
        InetAddress address = dp.getAddress();// 发送方的IP
        int port1 = dp.getPort();// 发送方的端口

        System.out.println(Thread.currentThread().getName() + "接收到：" + length + "_" + address + "_" + port1 + "_"
                + new String(data, 0, length));// 从0号索引开始，length个子节转为字符串

        // 4.释放资源
        ms.close();
    }

}
